package repository

import (
	"context"
	"fmt"
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm"
	"techoiceness.com/aiagent/llm-gateway/internal/entity"
)

// llmMessageRepository LLM消息存储库实现
type llmMessageRepository struct {
	db *gorm.DB
}

// NewLLMMessageRepository 创建LLM消息存储库
func NewLLMMessageRepository(db *gorm.DB) LLMMessageRepository {
	return &llmMessageRepository{db: db}
}

// GetMessagesByConversation 获取指定对话的所有消息
func (r *llmMessageRepository) GetMessagesByConversation(ctx context.Context, conversationID uuid.UUID) ([]entity.LLMMessage, error) {
	var messages []entity.LLMMessage

	err := r.db.WithContext(ctx).
		Where("conversation_id = ?", conversationID).
		Order("created_at ASC").
		Find(&messages).Error

	if err != nil {
		return nil, fmt.Errorf("failed to get messages: %w", err)
	}

	return messages, nil
}

// GetMessagesPaginated 分页获取对话消息
func (r *llmMessageRepository) GetMessagesPaginated(ctx context.Context, conversationID uuid.UUID, limit, offset int) ([]entity.LLMMessage, int64, error) {
	var messages []entity.LLMMessage
	var total int64

	// 获取总数
	err := r.db.WithContext(ctx).
		Model(&entity.LLMMessage{}).
		Where("conversation_id = ?", conversationID).
		Count(&total).Error

	if err != nil {
		return nil, 0, fmt.Errorf("failed to count messages: %w", err)
	}

	// 获取分页数据
	err = r.db.WithContext(ctx).
		Where("conversation_id = ?", conversationID).
		Order("created_at ASC").
		Limit(limit).
		Offset(offset).
		Find(&messages).Error

	if err != nil {
		return nil, 0, fmt.Errorf("failed to get paginated messages: %w", err)
	}

	return messages, total, nil
}

// GetLatestMessages 获取最新的N条消息
func (r *llmMessageRepository) GetLatestMessages(ctx context.Context, conversationID uuid.UUID, limit int) ([]entity.LLMMessage, error) {
	var messages []entity.LLMMessage

	err := r.db.WithContext(ctx).
		Where("conversation_id = ?", conversationID).
		Order("created_at DESC").
		Limit(limit).
		Find(&messages).Error

	if err != nil {
		return nil, fmt.Errorf("failed to get latest messages: %w", err)
	}

	// 反转顺序，确保时间顺序正确
	for i, j := 0, len(messages)-1; i < j; i, j = i+1, j-1 {
		messages[i], messages[j] = messages[j], messages[i]
	}

	return messages, nil
}

// SaveMessage 保存单条消息
func (r *llmMessageRepository) SaveMessage(ctx context.Context, message *entity.LLMMessage) error {
	if err := r.db.WithContext(ctx).Create(message).Error; err != nil {
		return fmt.Errorf("failed to save message: %w", err)
	}
	return nil
}

// SaveMessages 批量保存消息
func (r *llmMessageRepository) SaveMessages(ctx context.Context, messages []*entity.LLMMessage) error {
	if len(messages) == 0 {
		return nil
	}

	// 使用事务确保数据一致性
	return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(&messages).Error; err != nil {
			return fmt.Errorf("failed to save messages: %w", err)
		}
		return nil
	})
}

// DeleteMessage 删除指定消息
func (r *llmMessageRepository) DeleteMessage(ctx context.Context, messageID uint) error {
	result := r.db.WithContext(ctx).
		Where("id = ?", messageID).
		Delete(&entity.LLMMessage{})

	if result.Error != nil {
		return fmt.Errorf("failed to delete message: %w", result.Error)
	}

	if result.RowsAffected == 0 {
		return fmt.Errorf("message not found")
	}

	return nil
}

// DeleteMessagesByConversation 删除指定对话的所有消息
func (r *llmMessageRepository) DeleteMessagesByConversation(ctx context.Context, conversationID uuid.UUID) error {
	result := r.db.WithContext(ctx).
		Where("conversation_id = ?", conversationID).
		Delete(&entity.LLMMessage{})

	if result.Error != nil {
		return fmt.Errorf("failed to delete messages: %w", result.Error)
	}

	return nil
}

// UpdateMessage 更新消息内容
func (r *llmMessageRepository) UpdateMessage(ctx context.Context, messageID uint, content string) error {
	result := r.db.WithContext(ctx).
		Model(&entity.LLMMessage{}).
		Where("id = ?", messageID).
		Update("content", content)

	if result.Error != nil {
		return fmt.Errorf("failed to update message: %w", result.Error)
	}

	if result.RowsAffected == 0 {
		return fmt.Errorf("message not found")
	}

	return nil
}

// GetMessageCount 获取指定对话的消息数量
func (r *llmMessageRepository) GetMessageCount(ctx context.Context, conversationID uuid.UUID) (int64, error) {
	var count int64

	err := r.db.WithContext(ctx).
		Model(&entity.LLMMessage{}).
		Where("conversation_id = ?", conversationID).
		Count(&count).Error

	if err != nil {
		return 0, fmt.Errorf("failed to count messages: %w", err)
	}

	return count, nil
}

// GetTotalMessageCount 获取所有消息总数
func (r *llmMessageRepository) GetTotalMessageCount(ctx context.Context) (int64, error) {
	var count int64

	err := r.db.WithContext(ctx).
		Model(&entity.LLMMessage{}).
		Count(&count).Error

	if err != nil {
		return 0, fmt.Errorf("failed to count total messages: %w", err)
	}

	return count, nil
}

// GetMessageByID 根据ID获取单个消息
func (r *llmMessageRepository) GetMessageByID(ctx context.Context, messageID uint) (*entity.LLMMessage, error) {
	var message entity.LLMMessage

	err := r.db.WithContext(ctx).
		Where("id = ?", messageID).
		First(&message).Error

	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, fmt.Errorf("failed to get message by ID: %w", err)
	}

	return &message, nil
}

// CleanupOldMessages 清理旧消息
func (r *llmMessageRepository) CleanupOldMessages(ctx context.Context, before time.Time) (int64, error) {
	result := r.db.WithContext(ctx).
		Where("created_at < ?", before).
		Delete(&entity.LLMMessage{})

	if result.Error != nil {
		return 0, fmt.Errorf("failed to cleanup old messages: %w", result.Error)
	}

	return result.RowsAffected, nil
}

// GetMessagesByClientMessageID 根据客户端消息ID获取对应的所有LLM消息（按序号排序）
func (r *llmMessageRepository) GetMessagesByClientMessageID(ctx context.Context, clientMessageID uuid.UUID) ([]entity.LLMMessage, error) {
	var messages []entity.LLMMessage

	err := r.db.WithContext(ctx).
		Where("client_message_id = ?", clientMessageID).
		Order("message_sequence ASC").
		Find(&messages).Error

	if err != nil {
		return nil, fmt.Errorf("failed to get messages by client message ID: %w", err)
	}

	return messages, nil
}

// GetNextMessageSequence 获取客户端消息对应的下一个消息序号
func (r *llmMessageRepository) GetNextMessageSequence(ctx context.Context, clientMessageID uuid.UUID) (int, error) {
	var maxSequence int

	err := r.db.WithContext(ctx).
		Model(&entity.LLMMessage{}).
		Where("client_message_id = ?", clientMessageID).
		Select("COALESCE(MAX(message_sequence), -1)").
		Scan(&maxSequence).Error

	if err != nil {
		return 0, fmt.Errorf("failed to get next message sequence: %w", err)
	}

	return maxSequence + 1, nil
}
